package com.ccteam.fluidmusic.ui.nowplaying

import android.content.res.ColorStateList
import android.content.res.Configuration
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.support.v4.media.session.PlaybackStateCompat
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.bumptech.glide.Glide
import com.ccteam.fluidmusic.R
import com.ccteam.fluidmusic.databinding.FragmentControlPlayerBinding
import com.ccteam.fluidmusic.fluidmusic.common.utils.AlbumArtCache
import com.ccteam.fluidmusic.fluidmusic.media.extensions.*
import com.ccteam.fluidmusic.utils.PaletteUtils
import com.ccteam.fluidmusic.utils.showHide
import com.ccteam.fluidmusic.view.bean.NowPlayingMediaData
import com.ccteam.fluidmusic.widget.SNACKBAR_BOTTOM
import com.ccteam.fluidmusic.widget.snackbar
import com.ccteam.fluidmusic.ui.MainActivityViewModel
import com.google.android.material.slider.Slider
import com.orhanobut.logger.Logger
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import javax.inject.Inject
import kotlin.math.min


@AndroidEntryPoint
class ControlPlayerFragment : Fragment() {
    private var _binding: FragmentControlPlayerBinding? = null
    private val binding get() = _binding!!

    private var scheduleFuture: ScheduledFuture<*>? = null
    private val updateHandler = ControlHandler()
    private val positionUpdateExecutor = Executors.newSingleThreadScheduledExecutor()

    private var defaultColor: Array<Int> = arrayOf(Color.BLACK,Color.BLACK)

    /**
     * 因为此Fragment在ViewPager中，需要使用parentFragment的生命周期共享这个ViewModel
     */
    private val nowPlayingViewModel by viewModels<NowPlayingViewModel>(ownerProducer = { parentFragment ?: this})

    private val mainActivityViewModel by activityViewModels<MainActivityViewModel>()

    @Inject lateinit var albumArtCache: AlbumArtCache

    companion object {

        const val PROGRESS_UPDATE_INTERNAL = 1000L
        /**
         * 用于position字符串更新的缓冲
         */
        private val positionStringBuilder = StringBuilder(6)

        @JvmStatic
        fun newInstance(): ControlPlayerFragment {
            return ControlPlayerFragment()
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentControlPlayerBinding.inflate(inflater,container,false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        binding.sliderProgress.addOnSliderTouchListener(sliderTouchListener)
        binding.sliderProgress.addOnChangeListener(sliderChangeListener)

        binding.btnPrevious.setOnClickListener {
            mainActivityViewModel.skipPrevious()
        }

        binding.btnNext.setOnClickListener {
            mainActivityViewModel.skipNext()
        }

        binding.btnPausePlay.setOnClickListener {
            mainActivityViewModel.playOrPause()
        }

        binding.btnShuffle.setOnClickListener {
            if(mainActivityViewModel.shuffleMode.value == false){
                mainActivityViewModel.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_ALL)
                view.snackbar(R.string.description_shuffle_enabled, SNACKBAR_BOTTOM).show()
            } else {
                mainActivityViewModel.setShuffleMode(PlaybackStateCompat.SHUFFLE_MODE_NONE)
                view.snackbar(R.string.description_shuffle_disabled, SNACKBAR_BOTTOM).show()
            }
        }

        binding.btnRepeat.setOnClickListener {
            when(mainActivityViewModel.repeatMode.value?.first){
                PlaybackStateCompat.REPEAT_MODE_ONE ->{
                    mainActivityViewModel.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_NONE)
                    view.snackbar(R.string.description_repeat_off, SNACKBAR_BOTTOM).show()
                }
                PlaybackStateCompat.REPEAT_MODE_ALL,
                PlaybackStateCompat.REPEAT_MODE_GROUP ->{
                    mainActivityViewModel.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_ONE)
                    view.snackbar(R.string.description_repeat_one, SNACKBAR_BOTTOM).show()
                }
                else ->{
                    mainActivityViewModel.setRepeatMode(PlaybackStateCompat.REPEAT_MODE_ALL)
                    view.snackbar(R.string.description_repeat_all, SNACKBAR_BOTTOM).show()
                }
            }
        }

        binding.btnBitrate.setOnClickListener {
            findNavController().navigate(NowPlayingFragmentDirections.actionNowPlayingFragmentToSelectBitrateDialog())
        }

        mainActivityViewModel.mediaAlbumArt.observe(viewLifecycleOwner, {
            updateAlbumArt(it)
        })

        mainActivityViewModel.mediaButtonRes.observe(viewLifecycleOwner, { res ->
            binding.btnPausePlay.setIconResource(res)
        })

        mainActivityViewModel.nowPlayingMediaData.observe(viewLifecycleOwner, {
            updateStateUI(it)
        })

        mainActivityViewModel.shuffleMode.observe(viewLifecycleOwner, {
            updateShuffleModeUI(it,nowPlayingViewModel.fluidColor.value)
        })

        mainActivityViewModel.repeatMode.observe(viewLifecycleOwner, {
            updateRepeatModeUI(it)
        })

        nowPlayingViewModel.playbackStateLiveData.observe(viewLifecycleOwner, { state ->
            updatePosition()

            binding.progressBuffering.showHide(state.isOnlyBuffering)

            if(state.isOnlyPlaying){
                // 更新时再次取消，防止有时没有成功取消的问题
                binding.progressBuffering.showHide(false)
                schedulePositionUpdate()
            } else {
                cancelPositionUpdate()
            }
        })

        nowPlayingViewModel.fluidColor.observe(viewLifecycleOwner, {
            if(it == null){
                return@observe
            }
            updateFluidUI(it)
            updateShuffleModeUI(mainActivityViewModel.shuffleMode.value,it)
        })
    }

    /**
     * 当在ViewPager的其他Fragment中时停止进度计时
     */
    override fun onPause() {
        super.onPause()
        cancelPositionUpdate()
    }

    /**
     * 当在来到当前Fragment中时重新开始进度计时
     */
    override fun onResume() {
        super.onResume()
        updatePosition()
        schedulePositionUpdate()
    }


    /**
     * 更新封面内容
     * 使用协程进行获取封面Bitmap
     * 如果获取失败或者其他情况，设置为默认封面
     */
    private fun updateAlbumArt(albumArtUri: Pair<Uri?,Uri?>){
        val (cacheKeyUri,realParseUri) = albumArtUri
        if(cacheKeyUri != null && realParseUri != null){
            Logger.d("Cache:$cacheKeyUri -- Real:$realParseUri")
            viewLifecycleOwner.lifecycleScope.launch {
                albumArtCache.resolveBitmapByUri(
                    cacheKeyUri,
                    realParseUri,
                    isFull = true,
                    {
                        // 获取失败的封面则更新为默认颜色，此时如果是灵动模式不用更新颜色
                        if(!it && nowPlayingViewModel.shouldEnablePalette){
                            nowPlayingViewModel.resetFluidColor()
                        }
                        binding.ivAlbumArt.setImageResource(R.drawable.img_default_album)
                    },{ bitmap ->
                        Glide.with(binding.ivAlbumArt)
                            .load(bitmap)
                            .into(binding.ivAlbumArt)
                        // 如果是灵动模式则不用进行取色操作
                        if(nowPlayingViewModel.shouldEnablePalette){
                            viewLifecycleOwner.lifecycleScope.launch {
                                val colorPair = PaletteUtils.resolveBitmap(isNightMode(),bitmap,defaultColor[0])
                                nowPlayingViewModel.setFluidColor(colorPair)
                            }
                        }

                    }
                )
            }
        } else {
            binding.ivAlbumArt.setImageResource(R.drawable.img_default_album)
        }
    }

    /**
     * 更新状态UI内容
     */
    private fun updateStateUI(mediaData: NowPlayingMediaData) = with(binding){
        tvDuration.text = DateUtils.formatElapsedTime(positionStringBuilder,mediaData.duration/1000)
        sliderProgress.valueFrom = 0f
        sliderProgress.valueTo = mediaData.duration.toFloat()
        tvMusicTitle.text = mediaData.title
        tvMusicSubtitle.text = getString(R.string.now_playing_subtitle,mediaData.artist,mediaData.album)
        // 更新位置
        updatePosition()
    }

    /**
     * 更新随机播放模式UI
     */
    private fun updateShuffleModeUI(shuffleMode: Boolean?,colorPair: Pair<Int,Int>?){
        if(shuffleMode == true){
            colorPair?.let{
                binding.btnShuffle.backgroundTintList = ColorStateList.valueOf(colorPair.second)
            }
        } else {
            binding.btnShuffle.backgroundTintList = ColorStateList.valueOf(Color.TRANSPARENT)
        }
    }

    /**
     * 更新重复播放模式UI
     * 分为 单曲循环 和 顺序播放 两种模式
     */
    private fun updateRepeatModeUI(repeatMode: Pair<Int,Int>){
        binding.btnRepeat.setIconResource(repeatMode.second)
    }

    /**
     * 更新灵动UI
     */
    private fun updateFluidUI(colorPair: Pair<Int,Int>) = with(binding){
        val primaryColor = colorPair.first
        val primaryAlphaColor = colorPair.second
        val colorStatePrimary = ColorStateList.valueOf(primaryColor)
        tvMusicTitle.setTextColor(primaryColor)
        tvMusicSubtitle.setTextColor(primaryColor)
        btnPausePlay.iconTint = colorStatePrimary
        btnPrevious.iconTint = colorStatePrimary
        btnNext.iconTint = colorStatePrimary
        btnShuffle.iconTint = colorStatePrimary
        btnRepeat.iconTint = colorStatePrimary
        sliderProgress.thumbTintList = colorStatePrimary
        sliderProgress.trackActiveTintList = colorStatePrimary
        sliderProgress.trackInactiveTintList = ColorStateList.valueOf(primaryAlphaColor)
        tvPosition.setTextColor(primaryColor)
        tvDuration.setTextColor(primaryColor)
        btnBitrate.iconTint = colorStatePrimary
        progressBuffering.setIndicatorColor(primaryColor)
    }

    /**
     * 更新当前播放位置
     */
    private fun updatePosition(){
        val position = min(nowPlayingViewModel.playbackStateLiveData.value?.currentPlaybackPosition?.toFloat() ?: 0f
            ,binding.sliderProgress.valueTo)
        binding.sliderProgress.value = position
    }

    /**
     * 滑块触摸事件监听
     */
    private val sliderTouchListener = object: Slider.OnSliderTouchListener{
        /**
         * 当开始触摸时调用
         */
        override fun onStartTrackingTouch(slider: Slider) {
            cancelPositionUpdate()
        }

        /**
         * 当停止触摸时调用
         */
        override fun onStopTrackingTouch(slider: Slider) {
            mainActivityViewModel.seekTo(slider.value.toLong())
            schedulePositionUpdate()
        }
    }

    /**
     * 滑块值改变监听
     * 改变后更新相应文字，这里使用了 [StringBuilder] 做缓存
     * 防止频繁创建字符串
     */
    private val sliderChangeListener =
        Slider.OnChangeListener { _, value, _ ->
            binding.tvPosition.text = DateUtils.formatElapsedTime(positionStringBuilder,value.toLong()/1000)
        }

    /**
     * 更新播放位置的执行计划
     * 每隔 [PROGRESS_UPDATE_INTERNAL] 秒执行一次更新计划
     */
    private fun schedulePositionUpdate(){
        cancelPositionUpdate()
        if(!positionUpdateExecutor.isShutdown){
            scheduleFuture = positionUpdateExecutor.scheduleAtFixedRate({
                    updateHandler.post {
                        updatePosition()
                    }
                }, PROGRESS_UPDATE_INTERNAL, PROGRESS_UPDATE_INTERNAL,
                java.util.concurrent.TimeUnit.MILLISECONDS
            )
        }
    }

    /**
     * 取消位置更新的计划
     */
    private fun cancelPositionUpdate(){
        scheduleFuture?.cancel(true)
    }

    /**
     * 判断是否为暗黑模式
     */
    private fun isNightMode(): Boolean{
        return when(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK){
            Configuration.UI_MODE_NIGHT_YES -> true
            else -> false
        }
    }

    /**
     * 使用内部静态类持有Handler
     * 防止因为Handler持有该Fragment导致Fragment无法回收内存泄漏
     */
    class ControlHandler: Handler(Looper.getMainLooper())

    /**
     * 当View摧毁时停止计划
     */
    override fun onDestroyView() {
        super.onDestroyView()
        cancelPositionUpdate()
        scheduleFuture = null

        // 移除所有滑动条的监听
        binding.sliderProgress.clearOnChangeListeners()
        binding.sliderProgress.clearOnSliderTouchListeners()

        _binding = null
    }

}